/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.letmeshare.pedagogue.core.module;

import java.util.HashSet;
import java.util.Set;
import javax.persistence.EntityManager;
import org.letmeshare.pedagogue.core.entities.Person;
import org.letmeshare.pedagogue.core.entities.Role;
import org.letmeshare.pedagogue.core.entities.RoleInstance;
import org.letmeshare.pedagogue.core.validation.BusinessValidationException;

/**
 *
 * @author ibisuser1
 */
public class PersonModule extends AbstractModule{
    
    public static void createPerson(EntityManager em, Person person) {
        checkEntityManager(em);
        if(person == null)  {
            throw new IllegalArgumentException("Person required");
        }
        person.validate();
        em.persist(person);
    }
    
    public static void updatePersonProfile (EntityManager em, Person person) {
        checkEntityManager(em);
        if(person == null)  {
            throw new IllegalArgumentException("Person required");
        }
        Person oldPerson = getPerson(em, person.getUid());
        if (oldPerson == null) {
            throw new BusinessValidationException("Person doesn't exist");
        }
        Set<RoleInstance> existingRoles = oldPerson.getRoles();
        person.setRoles(existingRoles);
        person.setCredentials(oldPerson.getCredentials());
        person.validate();
        em.merge(person);
    }
    
    public static Person getPerson (EntityManager em, String id) {
        checkEntityManager(em);
        return em.find(Person.class, id);
    }
    
    public static void assignRoles (EntityManager em, Person person, Set<RoleInstance> roles) {
        checkEntityManager(em);
        if (person == null) {
            throw new IllegalArgumentException("Person required");
        }
        if (roles == null || roles.isEmpty()) {
            throw new IllegalArgumentException("At least one role required");
        }
        person = getPerson(em, person.getUid());
        if (person == null) {
            throw new BusinessValidationException("Person does not exist");
        }
        Set<RoleInstance> existingRoles = person.getRoles();
        if (existingRoles == null) {
            existingRoles = new HashSet<RoleInstance>();
        }
        Set<Role> availableRoles = OrganizationModule.getAvailableRoles(em, person.getUid().split("\\.")[0]);
        for (RoleInstance newRole : roles) {
            if (existingRoles.contains(newRole)) {
                throw new BusinessValidationException("Person already owns role : " + newRole.getRole().getName());
            }
            if (!availableRoles.contains(newRole.getRole())) {
                throw new BusinessValidationException("Invalid role : " + newRole.getRole().getName());
            }
            existingRoles.add(newRole);
        }
        if (!existingRoles.isEmpty()) {
            person.setRoles(existingRoles);
            em.merge(person);
        }
    }
    
    public static void assignRole (EntityManager em, Person person, RoleInstance role) {
        checkEntityManager(em);
        if (role == null) {
            throw new IllegalArgumentException("Role details required");
        }
        if (person == null) {
            throw new IllegalArgumentException("Person required");
        }
        person = getPerson(em, person.getUid());
        if (person == null) {
            throw new BusinessValidationException("Person does not exist");
        }
        Set<RoleInstance> existingRoles = person.getRoles();
        if (existingRoles == null) {
            existingRoles = new HashSet<RoleInstance>();
        }
        Set<Role> availableRoles = OrganizationModule.getAvailableRoles(em, person.getUid().split("\\.")[0]);
        if (role.getRole() == null || !availableRoles.contains(role.getRole())) {
            throw new BusinessValidationException("Invalid role");
        }
        if (existingRoles.contains(role)) {
            throw new BusinessValidationException("Duplicate role");
        }
        role.validate();
        existingRoles.add(role);
        person.setRoles(existingRoles);
        em.merge(person);
    }
    
    private static Set<String> getRoleNames (Set<RoleInstance> roles) {
        if (roles == null) {
            return null;
        }
        Set<String> roleNames = new HashSet<String>();
        for (RoleInstance role : roles) {
            roleNames.add(role.getRole().getName());
        }
        return roleNames;
    }
}
